package com.example.multinetty.netty.thirdprotocal;


import com.alibaba.fastjson.JSONObject;
import com.example.multinetty.netty.config.DispatchServletFactory;
import com.example.multinetty.netty.secondprotocal.CompositeFullHttp;
import com.example.multinetty.netty.session.LocalSession;

import com.example.multinetty.netty.thirdprotocal.dao.Player;
import com.example.multinetty.netty.thirdprotocal.vo.chat.PrivateChatRequest;
import com.example.multinetty.netty.thirdprotocal.vo.chat.PublicChatRequest;
import com.example.multinetty.netty.thirdprotocal.vo.player.LoginRequest;
import com.example.multinetty.netty.thirdprotocal.vo.player.PlayerResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;

import java.net.URI;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * 消息接受处理类
 * @author -琴兽-
 *
 */
@ChannelHandler.Sharable
@Component
@Slf4j
public class ServerHandler extends SimpleChannelInboundHandler<Request> implements ApplicationContextAware {
	private ApplicationContext applicationContext;

	@Autowired
	private DispatchServletFactory dispatchServletFactory;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext){
		this.applicationContext = applicationContext;
	}

	/**
	 * 接收消息
	 */
	@Override
	public void channelRead0(ChannelHandlerContext ctx, Request request) throws Exception {
		//根据解码后的类，来获取url的地址
		ModuleCMDEnum moduleCMDEnum=ModuleCMDEnum.getByModuleandCmd(request.getModule(), request.getCmd());
		String urlfullpath="";
		if(moduleCMDEnum!=null){
			urlfullpath=moduleCMDEnum.fixUrlpath+moduleCMDEnum.independantpath;
		}
		URI uri=new URI(urlfullpath);//实际上需要从协议包中获取
		FullHttpRequest fullHttpRequest=new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST,uri.toASCIIString());
		FullHttpWithRequest fullHttpWithRequest=new FullHttpWithRequest();
		fullHttpWithRequest.setFullHttpRequest(fullHttpRequest);
		fullHttpWithRequest.setRequest(request);
		MockHttpServletRequest servletRequest = createServletRequest(fullHttpWithRequest);
		MockHttpServletResponse servletResponse = new MockHttpServletResponse();
		handleSession(ctx,servletRequest);
		/*LoginRequest loginRequest=null;
		PublicChatRequest publicChatRequest=null;
		PrivateChatRequest privateChatRequest=null;
		String objectToJson="";
		ObjectMapper objectMapper = new ObjectMapper();
		if(moduleCMDEnum.module==1) {
			*//*loginRequest = parseContent(request.getData());
			objectToJson = objectMapper.writeValueAsString(loginRequest);*//*
			servletRequest.setContent(request.getData());
		}
		if(moduleCMDEnum.module==2 && moduleCMDEnum.command==1){
			publicChatRequest=parsepbulicContent(request.getData());
			objectToJson = objectMapper.writeValueAsString(publicChatRequest);
		}
		if(moduleCMDEnum.module==2 && moduleCMDEnum.command==2){
			privateChatRequest=parseprivatechateContent(request.getData());
			objectToJson = objectMapper.writeValueAsString(privateChatRequest);
		}

		// 将Java对象序列化为Json字符串

		log.info("String(objectToJson):"+objectToJson);

		//byte[] requestcontent=JSONObject.parseObject(loginRequest).toJSONString(request.getData()).getBytes(StandardCharsets.UTF_8);
		servletRequest.setContent(objectToJson.getBytes(StandardCharsets.UTF_8));*/
		servletRequest.setContent(request.getData());
		log.info("String(request.getData()):"+new String(request.getData()));
		DispatcherServlet servlet = dispatchServletFactory.getByProxy("NettyChatProtocal");
		//spring容器已经启动过，这个时候DispatcherServlet要进行初始化new，并进行配置。因为DispatcherServlet，无法获得实例，所以采用继承的方式新建一个。MyServlet
		servlet.service(servletRequest, servletResponse);
		HttpResponseStatus status = HttpResponseStatus.valueOf(servletResponse.getStatus());
		Response response=new Response(request);

			String result = servletResponse.getContentAsString();
			log.info("springmvc返回的结果是:" + result);
			if((JSONObject) JSONObject.parseObject(result, Result.class).getContent()!=null) {
				JSONObject jsonObject = (JSONObject) JSONObject.parseObject(result, Result.class).getContent();

				//Result<?> result1=(Result<?>)JSONObject.parse(result);
				//下面是开始统一进行转换，将返回的json转换为
				log.info("springmvc返回的结果是,result中的内容:" + jsonObject);
				//Response response = new Response(request);

				response.setData(jsonObject.toJSONString().getBytes(StandardCharsets.UTF_8));
			}else {
				response.setData(null);
			}

		ctx.writeAndFlush(response);
		//handlerMessage(new SessionImpl(ctx.channel()), request);

	}

	private PrivateChatRequest parseprivatechateContent(byte[] data) {
		ByteBufAllocator bufAllocator = PooledByteBufAllocator.DEFAULT;
		ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN;
		//readBuffer = BufferFactory.getBuffer(data);
		ByteBuf buffer = bufAllocator.heapBuffer();
		buffer = BufferFactory.getBuffer(data);
		//buffer = buffer.order(BYTE_ORDER);
		PrivateChatRequest privateChatRequest=new PrivateChatRequest();
		privateChatRequest.setTargetPlayerId(buffer.readLong());
		privateChatRequest.setContext(readString(buffer));
		//privateChatRequest.setContext(readString(buffer));
		/*LoginRequest loginRequest=new LoginRequest();
		loginRequest.setPlayerName(readString(buffer));
		loginRequest.setPassward(readString(buffer));*/
		return privateChatRequest;
	}

	private PublicChatRequest parsepbulicContent(byte[] data) {
		//虽然已经是byte[]，但是还需要转为ByteBuf来进行解码
		ByteBufAllocator bufAllocator = PooledByteBufAllocator.DEFAULT;
		ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN;
		//readBuffer = BufferFactory.getBuffer(data);
		ByteBuf buffer = bufAllocator.heapBuffer();
		buffer = BufferFactory.getBuffer(data);
		//buffer = buffer.order(BYTE_ORDER);
		PublicChatRequest publicChatRequest=new PublicChatRequest();
		publicChatRequest.setContext(readString(buffer));
		/*LoginRequest loginRequest=new LoginRequest();
		loginRequest.setPlayerName(readString(buffer));
		loginRequest.setPassward(readString(buffer));*/
		return publicChatRequest;
	}

	private LoginRequest parseContent(byte[] data) {
		//虽然已经是byte[]，但是还需要转为ByteBuf来进行解码
		ByteBufAllocator bufAllocator = PooledByteBufAllocator.DEFAULT;
		ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN;
		//readBuffer = BufferFactory.getBuffer(data);
		ByteBuf buffer = bufAllocator.heapBuffer();
		buffer = BufferFactory.getBuffer(data);
		//buffer = buffer.order(BYTE_ORDER);
		LoginRequest loginRequest=new LoginRequest();
		loginRequest.setPlayerName(readString(buffer));
		loginRequest.setPassward(readString(buffer));
		return loginRequest;
	}
	public String readString(ByteBuf readBuffer) {
		int size = readBuffer.readShort();
		if (size <= 0) {
			return "";
		}

		byte[] bytes = new byte[size];
		readBuffer.readBytes(bytes);

		return new String(bytes, Charset.forName("UTF-8"));
	}


	private MockHttpServletRequest createServletRequest(FullHttpWithRequest fullHttpWithRequest ) {
		FullHttpRequest fullHttpRequest=fullHttpWithRequest.getFullHttpRequest();
		UriComponents uriComponents = UriComponentsBuilder.fromUriString(fullHttpRequest.getUri()).build();

		//MockHttpServletRequest servletRequest = new MockHttpServletRequest(this.servletContext);
		MockHttpServletRequest servletRequest = new MockHttpServletRequest();
		servletRequest.setRequestURI(uriComponents.getPath());
		servletRequest.setPathInfo(uriComponents.getPath());
		servletRequest.setMethod(fullHttpRequest.getMethod().name());

		/*HttpSession httpSession=new MockHttpSession();
		servletRequest.setSession(httpSession);*/

		if (uriComponents.getScheme() != null) {
			servletRequest.setScheme(uriComponents.getScheme());
		}
		if (uriComponents.getHost() != null) {
			servletRequest.setServerName(uriComponents.getHost());
		}
		if (uriComponents.getPort() != -1) {
			servletRequest.setServerPort(uriComponents.getPort());
		}
		fullHttpRequest.headers().set("Content-Type","application/json;charset=UTF-8");

		for (String name : fullHttpRequest.headers().names()) {
			servletRequest.addHeader(name, fullHttpRequest.headers().get(name));
		}
		servletRequest.setContent(fullHttpWithRequest.getRequest().getData());
		//servletRequest.addHeader("Content-Type","application/json;charset=UTF-8");
		/*try {
			ByteBuf buf=fullHttpRequest.content();
			int readable=buf.readableBytes();
			byte[] bytes=new byte[readable];
			buf.readBytes(bytes);
			bytes=compositeFullHttp.getContents();
			String contentStr=UriUtils.decode(new String(bytes,"UTF-8"),"UTF-8");
			System.out.println("http post请求写入数据:"+contentStr);
			fullHttpRequest.content().release();
		}catch (Exception ex){

		}*/

		//		ByteBuf bbContent = fullHttpRequest.content();
//		if(bbContent.hasArray()) {
//			byte[] baContent = bbContent.array();
//			servletRequest.setContent(baContent);
//		}

		// 将post请求的参数，添加到HttpServletRrequest的parameter
       /* try {
            ByteBuf buf=fullHttpRequest.content();
            int readable=buf.readableBytes();
            byte[] bytes=new byte[readable];
            buf.readBytes(bytes);
            String contentStr = UriUtils.decode(new String(bytes,"UTF-8"), "UTF-8");
            for(String params : contentStr.split("&")){
                String[] para = params.split("=");
                if(para.length > 1){
                    servletRequest.addParameter(para[0],para[1]);
                } else {
                    servletRequest.addParameter(para[0],"");
                }
            }
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
*/
		try {
			if (uriComponents.getQuery() != null) {
				String query = UriUtils.decode(uriComponents.getQuery(), "UTF-8");
				servletRequest.setQueryString(query);
			}

			for (Map.Entry<String, List<String>> entry : uriComponents.getQueryParams().entrySet()) {
				for (String value : entry.getValue()) {
					servletRequest.addParameter(
							UriUtils.decode(entry.getKey(), "UTF-8"),
							UriUtils.decode(value, "UTF-8"));
				}
			}
		}
	/*	catch (UnsupportedEncodingException ex) {
			// shouldn't happen
		}*/
		catch (Exception ex) {
			// shouldn't happen
		}

		return servletRequest;
	}
	private void handleSession(ChannelHandlerContext context,MockHttpServletRequest servletRequest) {
		ChatSession chatSession=new ChatSession(context.channel());
		//chatSession.bind();
		//这个地方，需要调整一下，因为servletRequest是单例，它要输入一个 userid，或playid作为key。这样能保证不重复。
		servletRequest.setAttribute("session",chatSession);
	}
	
	/**
	 * 消息处理
	 * @param channelId
	 * @param request
	 *//*
	private void handlerMessage(Session session, Request request){
		
		Response response = new Response(request);
		
		System.out.println("module:"+request.getModule() + "   " + "cmd：" + request.getCmd());
		
		//获取命令执行器
		Invoker invoker = InvokerHoler.getInvoker(request.getModule(), request.getCmd());
		if(invoker != null){
			try {
				Result<?> result = null;
				//假如是玩家模块传入channel参数，否则传入playerId参数
				if(request.getModule() == ModuleId.PLAYER){
					result = (Result<?>)invoker.invoke(session, request.getData());
				}else{
					Object attachment = session.getAttachment();
					if(attachment != null){
						Player player = (Player) attachment;
						//这个地方是直接发送到客户端
						result = (Result<?>)invoker.invoke(player.getPlayerId(), request.getData());
					}else{
						//会话未登录拒绝请求
						response.setStateCode(ResultCode.LOGIN_PLEASE);
						session.write(response);
						return;
					}
				}
				
				//判断请求是否成功
				if(result.getResultCode() == ResultCode.SUCCESS){
					//回写数据
					Object object = result.getContent();
					if(object != null){
						if(object instanceof Serializer){
							Serializer content = (Serializer)object;
							response.setData(content.getBytes());
						}else if(object instanceof GeneratedMessage){
							GeneratedMessage content = (GeneratedMessage)object;
							response.setData(content.toByteArray());
						}else{
							System.out.println(String.format("不可识别传输对象:%s", object));
						}
					}
					session.write(response);
				}else{
					//返回错误码
					response.setStateCode(result.getResultCode());
					session.write(response);
					return;
				}
			} catch (Exception e) {
				e.printStackTrace();
				//系统未知异常
				response.setStateCode(ResultCode.UNKOWN_EXCEPTION);
				session.write(response);
			}
		}else{
			//未找到执行者
			response.setStateCode(ResultCode.NO_INVOKER);
			session.write(response);
			return;
		}
	}*/
	
	/**
	 * 断线移除会话
	 */
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		ChatSession session = new ChatSession(ctx.channel());
		Object object = session.getAttachment();
		if(object != null){
			Player player = (Player)object;
			SessionManager.removeSession(player.getPlayerId());
		}
	}
}
